# -*- encoding: utf-8 -*-
import datetime

from django.utils.translation import ugettext as _

from google.appengine.ext import db

class MetricsView(db.Model):
    class NameMustBeUnique(Exception):
        """A name must be unique by table"""

    name = db.StringProperty(required=True)
    metrics_properties = db.StringListProperty()

    def put(self, creation=True):
        if creation and self.get_by_key_name(self._key_name):
            raise self.NameMustBeUnique
        return super(MetricsView, self).put()

class Property(db.Model):
    class DateInFuture(Exception):
        """The date is in the future"""
    user = db.UserProperty(required=True)
    date = db.DateTimeProperty(required=True,
                               auto_now_add=True)
    metrics_view = db.ReferenceProperty(MetricsView)

    @classmethod
    def _update_grapher(cls, grapher, user):
        """Method template"""
        return grapher

    @classmethod
    def get_chart_url(cls, user, metrics_view):
        property_instances = cls.gql("WHERE user=:1 AND date > :2 AND metrics_view = :3 ORDER BY date",
                                     user,
                                     datetime.datetime.now()-datetime.timedelta(days=30),
                                     metrics_view)
        values = []
        dates = []
        for property in property_instances:
            dates.append(property.date)
            values.append(property.value)
        if values and dates:
            from metrics.graph import Grapher 
            grapher = Grapher(cls.get_name(), dates, values)
            return cls._update_grapher(grapher, user).get_chart_url()

    def put(self):
        if self.date > datetime.datetime.now():
            raise self.DateInFuture
        return super(Property, self).put()
        
    @classmethod
    def get_name(cls):
        """Return the name of the property."""
        return _(unicode(cls.__name__))

    @classmethod
    def get_form(cls, data=None):
        """Return a form suitable for the edition of the current property"""
        raise NotImplementedError

    @classmethod
    def add_data(cls, user, date, metrics_view, data):
        valid = False
        form = cls.get_form(data)
        if form.is_valid():
            value = form.cleaned_data['value']
            if not value:
                valid = True
            else:
                instance = cls(user=user,
                               date=date,
                               metrics_view=metrics_view,
                               value=value)
                instance.put()
                valid = True
        return valid, form

    
class IntegerProperty(Property):
    value = db.IntegerProperty(required=True)
    

class Properties(object):
    def __init__(self):
        self.properties = {}

    def add(self, class_instance):
        self.properties[class_instance.__name__] = (class_instance.get_name(), class_instance)

    def formated_data(self):
        """Return a list of tuple containing the displayable name and the unique name of each property.
        e.g. [('Weight', 'weight'), ('max length', 'max_length')]"""
        data = []
        for id, (name, instance) in self.properties.iteritems():
            data.append((id, name))
        data.sort(key = lambda a: a[0])
        return data

    def class_for_name(self, name):
        return self.properties[name][1]

properties = Properties()
